#include <iostream>
#include <vector>
#include <cstdio> 

#define in read()
#define fi first
#define se second
#define pb push_back

using namespace std;

typedef long long ll;
typedef double db;
typedef vector < int >  vec;
typedef pair < int , int > pii;

int read() {
    int x = 0; bool f = 0; char ch = getchar(); while(!isdigit(ch)) f |= ch == '-',ch = getchar();
    while(isdigit(ch)) x = x * 10 + (ch ^ 48),ch = getchar(); return f ? -x : x;
}

const int N = 5e4 + 10;
const int mod = 998244353;

int n,Q,K,fa[N],delta[N],ddel[N];
int dfn[N],siz[N],son[N],top[N],tim,ind[N],dep[N],ans[N];
vec G[N];
vector < pii > pot[N];

int upd(int x) { return x + (x >> 31 & mod); }

namespace seg {
    int sum[N << 2],val[N << 2],lz[N << 2];
    void pushup(int x) { sum[x] = ::upd(sum[x << 1] + sum[x << 1 | 1] - mod); val[x] = upd(val[x << 1] + val[x << 1 | 1] - mod); }
    void add(int o,int v) { val[o] = ::upd(val[o] + (ll) sum[o] * v % mod - mod); lz[o] = ::upd(lz[o] + v - mod); }
    void pushdn(int o) { if(lz[o]) add(o << 1,lz[o]),add(o << 1 | 1,lz[o]),lz[o] = 0; }
    void build(int o = 1,int l = 1,int r = n) {
	if(l == r) return sum[o] = ddel[ind[l]],val[o] = 0,void(); int mid = l + r >> 1;
	build(o << 1,l,mid); build(o << 1 | 1,mid + 1,r); pushup(o);
    }
    void upd(int xl,int xr,int v,int o = 1,int l = 1,int r = n) {
	if(xl == l && xr == r) return add(o,v); pushdn(o); int mid = l + r >> 1;
	if(xr <= mid) upd(xl,xr,v,o << 1,l,mid); else if(xl > mid) upd(xl,xr,v,o << 1 | 1,mid + 1,r);
	else upd(xl,mid,v,o << 1,l,mid),upd(mid + 1,xr,v,o << 1 | 1,mid + 1,r); pushup(o);
    }
    int query(int xl,int xr,int o = 1,int l = 1,int r = n) {
	if(xl == l && xr == r) return val[o]; pushdn(o); int mid = l + r >> 1;
	if(xr <= mid) return query(xl,xr,o << 1,l,mid); else if(xl > mid) return query(xl,xr,o << 1 | 1,mid + 1,r);
	else return ::upd(query(xl,mid,o << 1,l,mid) + query(mid + 1,xr,o << 1 | 1,mid + 1,r) - mod);
    }
    void modify(int x,int y,int v) {
	while(top[x] ^ top[y]) {
	    if(dep[top[x]] < dep[top[y]]) swap(x,y);
	    upd(dfn[top[x]],dfn[x],v); x = fa[top[x]];
	}
	if(dfn[x] > dfn[y]) swap(x,y); upd(dfn[x],dfn[y],v);
    }
    int qry(int x,int y) {
	int ans = 0;
	while(top[x] ^ top[y]) {
	    if(dep[top[x]] < dep[top[y]]) swap(x,y);
	    ans = ::upd(ans + query(dfn[top[x]],dfn[x]) - mod); x = fa[top[x]];
	}
	if(dfn[x] > dfn[y]) swap(x,y); ans = ::upd(ans + query(dfn[x],dfn[y]) - mod);
	return ans;
    }
}

void dfs(int x,int p) {
    fa[x] = p; siz[x] = 1; dep[x] = dep[p] + 1; ddel[x] = delta[dep[x]]; 
    for(auto y : G[x]) dfs(y,x),siz[x] += siz[y],son[x] = siz[y] > siz[son[x]] ? y : son[x];
}

void dfs1(int x,int anc) {
    ind[dfn[x] = ++tim] = x; top[x] = anc; if(son[x]) dfs1(son[x],anc);
    for(auto y : G[x]) if(y ^ son[x]) dfs1(y,y);
}

ll qp(ll x,int t) { ll res = 1; for(;t;t >>= 1,x = x * x % mod) if(t & 1) res = res * x % mod; return res; }

int main() {
#ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
#endif
    n = in,Q = in,K = in; for(int i = 2;i <= n;i++) fa[i] = in,G[fa[i]].pb(i);
    for(int i = 1;i <= n;i++) delta[i] = upd(qp(i,K) - qp(i - 1,K));
    dfs(1,0); dfs1(1,1); seg :: build(); 
    for(int i = 1,x,y;i <= Q;i++) x = in,y = in,pot[x].pb({y,i});
    for(int i = 1;i <= n;i++) {
	seg :: modify(i,1,1);
	for(auto d : pot[i]) ans[d.se] = seg :: qry(d.fi,1);
    }
    for(int i = 1;i <= Q;i++) printf("%d\n",ans[i]); return 0;
} 
